using System;
using System.Collections.Generic;
using Omu.ValueInjecter;
using Uber.Core.Model;
using Uber.Core.Repository;
using Uber.Data;
using System.Linq;

namespace Uber.Test
{

    public class FillCollections : NoSourceValueInjection
    {
        private readonly IUniRepo u;
        private readonly string parentName;
        private readonly object parentIdValue;
        private IDictionary<Type, string> pname;

        public FillCollections(IUniRepo u, string parentName, object parentIdValue, Dictionary<Type,string> pname)
        {
            this.pname = pname;
            this.u = u;
            this.parentName = parentName;
            this.parentIdValue = parentIdValue;
        }

        protected override void Inject(object target)
        {
            Console.WriteLine("fill collections for "+ target.GetType().Name);
             var props = target.GetProps();
             for (var j = 0; j < props.Count; j++)
             {
                 var p = props[j];
                 if (!p.PropertyType.IsGenericType || p.PropertyType.GetGenericTypeDefinition() != typeof (ICollection<>)) continue;
                 var t = p.PropertyType.GetGenericArguments()[0];
                 if (!t.IsSubclassOf(typeof (Entity))) continue;

                 var tlist = typeof (List<>).MakeGenericType(t);
                 dynamic list = Activator.CreateInstance(tlist);
                 Console.WriteLine("   creating a list of " + t.Name);
                 for (var k = 0; k < 3; k++)
                 {
                     Console.WriteLine("      create a " + t.Name);
                     dynamic o = Activator.CreateInstance(t).InjectFrom(new Fill(u, true,new[]{parentName+"Id", parentName}));
                     var x = (pname == null) ? parentName : pname[t];
                     o.GetType().GetProperty(x).SetValue(o,parentIdValue,null);
                     u.Add(o);
                     u.Save();
                     Console.WriteLine("      add " + t.Name + " to list");
                     list.Add(o);
                 }
                 p.SetValue(target, list);
             }
        }
    }

    public class Fill : NoSourceValueInjection
    {
        private readonly IUniRepo u;

        private static long s;
        private static int i;
        private readonly bool isChild;
        private readonly string[] banList;

        public Fill(IUniRepo u, bool isChild = false, string[] banList = null)
        {
            this.u = u;
            this.isChild = isChild;
            this.banList = banList;
        }

        protected override void Inject(object target)
        {
            var props = target.GetProps();
            for (var j = 0; j < props.Count; j++)
            {
                var p = props[j];
                if (banList != null && banList.Contains(p.Name)) continue;

                if (p.PropertyType == typeof(string)) p.SetValue(target, "a" + ++s);
                else if (p.PropertyType == typeof(int) && !p.Name.EndsWith("Id")) p.SetValue(target, ++i);
                else if (p.PropertyType == typeof(DateTime)) p.SetValue(target, DateTime.Now);
                else if (p.PropertyType.IsSubclassOf(typeof(Entity)) && !(isChild && target.GetType() == p.PropertyType))
                {
                    var ident = isChild ? "   " : "";
                    Console.WriteLine(ident + "   create " + p.PropertyType.Name  + " for " + target.GetType().Name);
                    dynamic o = Activator.CreateInstance(p.PropertyType).InjectFrom(new Fill(u, true));
                    u.Add(o);
                    u.Save();
                    p.SetValue(target, o);
                }
            }
        }
    }
}